//
// Created by tang on 23-3-26.
//

#include "panels.hpp"
#include <core/log_store.hpp>
#include "app/font_mgr.hpp"
#include "app/plugin_mgr.hpp"
#include "content/bindable.hpp"
#include "core/log.hpp"
#include "imgui.h"
#include "imgui_ext/ImFileDialog.h"
#include "imgui_ext/imgui_ext.h"
#include "imgui_ext/texture.h"
#include "imgui_internal.h"
#include "plugin/plugin_interface.hpp"
#include "text/IconsFontAwesome6.h"
#include "utils/io_tools.hpp"
#include "ui/ui_item.hpp"
#include "service/render_service.hpp"
#include "app/ui_test.hpp"

#include <content/image.hpp>

using namespace ImGui;

PANEL_IMPL (log, ICON_FA_COMMENT_DOTS " 日志信息", true)
{
    PushStyleVar (ImGuiStyleVar_WindowPadding, ImVec2(0,0));
    bool open = Begin (log_panel_name);
    PopStyleVar ();
    if (open) {
        PushStyleVar (ImGuiStyleVar_CellPadding, ImVec2(0,8.f));
        PushStyleVar (ImGuiStyleVar_ItemSpacing, ImVec2(0,2.f));

        static auto logger = log_store::instance();
        static bool auto_scroll = true;
        static const ImU32 level_colors[] {
                IM_COL32 (0xcd,0xcd,0xcd,0xff),
                IM_COL32 (0xff,0xff,0xff,0xff),
                IM_COL32 (0xcd,0xdc,0x39,0xff),
                IM_COL32 (0xff,0xea,0x00,0xff),
                IM_COL32 (0xff,0x17,0x44,0xff),
                IM_COL32 (0xff,0x00,0x00,0xff),
        };

        static u8 level;
        static char *payload_text = nullptr;
        static u32   payload_size = 0;
        ImGuiID detail_id = GetID("##PayloadDetails");

        PushStyleColor(ImGuiCol_ChildBg, GetStyleColorVec4 (ImGuiCol_Header));
        BeginChild("Filters", ImVec2(0, GetTextLineHeightWithSpacing()*1.5f));
        PopStyleColor();
        {
            static u32 filter_value = logger->filter_value();
            AlignTextToFramePadding();
            FontManager::instance()->use_fonts(1); // bold
            PushStyleColor (ImGuiCol_Text, level_colors[0]);
            if (CheckboxFlags(ICON_FA_CODE, &filter_value, 1 << 0))
            {
                logger->set_filter(0, filter_value & 0x1);
            }
            SameLine(0,GetFontSize() * .5f);
            PushStyleColor (ImGuiCol_Text, level_colors[1]);
            if (CheckboxFlags(ICON_FA_BUG, &filter_value, 1 << 1))
            {
                logger->set_filter(1, filter_value & 0x2);
            }
            SameLine(0,GetFontSize() * .5f);
            PushStyleColor (ImGuiCol_Text, level_colors[2]);
            if (CheckboxFlags(ICON_FA_CIRCLE_INFO, &filter_value, 1 << 2))
            {
                logger->set_filter(2, filter_value & 0x4);
            }
            SameLine(0,GetFontSize() * .5f);
            PushStyleColor (ImGuiCol_Text, level_colors[3]);
            if (CheckboxFlags(ICON_FA_TRIANGLE_EXCLAMATION, &filter_value, 1 << 3))
            {
                logger->set_filter(3, filter_value & 0x8);
            }
            SameLine(0,GetFontSize() * .5f);
            PushStyleColor (ImGuiCol_Text, level_colors[4]);
            if (CheckboxFlags(ICON_FA_CIRCLE_XMARK, &filter_value, 1 << 4))
            {
                logger->set_filter(4, filter_value & 0x10);
            }
            SameLine(0,GetFontSize() * .5f);
            PushStyleColor (ImGuiCol_Text, level_colors[5]);
            if (CheckboxFlags(ICON_FA_GHOST, &filter_value, 1 << 5))
            {
                logger->set_filter(5, filter_value & 0x20);
            }
            PopStyleColor (6);

            FontManager::instance()->use_fonts(0);

            auto const size1 = CalcTextSize ("\U0001f447");
            auto const size2 = CalcTextSize (ICON_FA_CLOCK_ROTATE_LEFT);
            auto const size3 = CalcTextSize (ICON_FA_TRASH);

            SameLine(GetWindowContentRegionWidth() - size1.x - size2.x - size3.x - GetFontSize() * 4.f);
            Checkbox ("\U0001f447", &auto_scroll);
            TextToolTipMaker("\U0001f447: 跟随最新一条日志显示");

            SameLine(GetWindowContentRegionWidth() - size2.x - size3.x - GetFontSize() * 2.f);
            if (Button(ICON_FA_CLOCK_ROTATE_LEFT)) {
                filter_value = 0xFF;
            }
            TextToolTipMaker(ICON_FA_CLOCK_ROTATE_LEFT ": 重置等级筛选器（显示所有日志）");

            SameLine(GetWindowContentRegionWidth() - size3.x - GetFontSize());
            PushStyleColor(ImGuiCol_Button, IM_COL32(210, 20, 20, 255));
            PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(225, 5, 5, 255));
            PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(250, 10, 10, 255));
            PushStyleColor(ImGuiCol_Text, IM_COL32(0, 0, 0, 255));
            if (Button(ICON_FA_TRASH))
                logger->clear();
            PopStyleColor(4);
            TextToolTipMaker(ICON_FA_TRASH ": 删除所有日志");
        }
        EndChild();

        // log content
        PushStyleColor(ImGuiCol_ChildBg, 0);
        BeginChild("Content");
        PopStyleColor();

        if (BeginTable("Log Content", 5,
                        ImGuiTableFlags_ContextMenuInBody |
                                ImGuiTableFlags_SizingStretchSame |
                                ImGuiTableFlags_ScrollY |
                                ImGuiTableFlags_RowBg
                        ))
        {
            FontManager::instance()->use_fonts(1);
            TableSetupColumn(" 日期", ImGuiTableColumnFlags_WidthFixed, GetFontSize()*12.f);
            TableSetupColumn(" 线程", ImGuiTableColumnFlags_WidthFixed, GetFontSize()*4.f);
            TableSetupColumn(" 等级", ImGuiTableColumnFlags_WidthFixed, GetFontSize()*3.f);
            TableSetupColumn(" 消息", ImGuiTableColumnFlags_WidthStretch);
            TableSetupColumn(" 操作", ImGuiTableColumnFlags_WidthFixed, GetFontSize()*6.f);

            TableSetupScrollFreeze(0, 1); // pin header row
            TableHeadersRow();
            FontManager::instance()->use_fonts(0);

            // log content
            auto iter = logger->logs();
            ImGuiListClipper clipper;
            clipper.Begin(iter.count());

            static const char *level_text[] {
                    "  " ICON_FA_CODE, "追踪",
                    "  " ICON_FA_BUG, "调试",
                    "  " ICON_FA_CIRCLE_INFO, "消息",
                    "  " ICON_FA_TRIANGLE_EXCLAMATION, "警告",
                    "  " ICON_FA_CIRCLE_XMARK, "错误",
                    "  " ICON_FA_GHOST, "致命",
            };

            while(clipper.Step()) {
                for (int i=clipper.DisplayStart; i<clipper.DisplayEnd; ++i) {

                    auto const log = iter[i];
                    if (!log) {
                        clipper.End();
                        break;
                    }

                    PushID(log);
                    PushStyleColor (ImGuiCol_Text, level_colors[log->level]);

                    TableNextColumn();
                    Dummy(ImVec2{GetFontSize(), 0});
                    SameLine();
                    TextUnformatted(log->datetime);
                    TableNextColumn();
                    Dummy(ImVec2{GetFontSize(), 0});
                    SameLine();
                    Text("%lu", log->thread_id);
                    TableNextColumn();
                    Text("%s", level_text[log->level * 2]);
                    if (IsItemHovered ())
                        SetTooltip ("%s", level_text[log->level*2 + 1]);
                    TableNextColumn();
                    TextUnformatted (log->payload, strchr (log->payload, '\n'));

                    PopStyleColor ();
                    
                    TableNextColumn();
                    Dummy(ImVec2(GetFontSize(), GetFontSize()));
                    SameLine();
                    if (Button(ICON_FA_CLIPBOARD)) {
                        SetClipboardText(log->payload);
                    }
                    TextToolTipMaker("复制消息");
                    SameLine(0, GetFontSize());
                    if (Button(ICON_FA_UP_RIGHT_FROM_SQUARE))
                    {
                        level = log->level;
                        payload_text = (char*)log->payload;
                        payload_size = log->payload_size;
                        OpenPopup(detail_id);
                    }
                    TextToolTipMaker("在独立窗口显示");
                    PopID();
                }
            }
            if (auto_scroll) {
                SetScrollY (GetScrollMaxY());
            }
            EndTable();
        }
        EndChild();
        PopStyleVar (2);

        CenterWindowPercent(.6f);
        if (BeginPopup("##PayloadDetails")) {
            PushStyleColor(ImGuiCol_Text, level_colors[level]);
            InputTextMultiline("##Details", payload_text, payload_size, ImVec2(-1,-1), ImGuiInputTextFlags_ReadOnly);
            PopStyleColor();
            EndPopup();
        }
    }
    End ();
}

#define INVALID_PLUGIN ((IPlugin*)intptr_t(-1))

static IPlugin *selected_plugin = INVALID_PLUGIN;
static const char *selected_path   = nullptr;

PANEL_IMPL (plugin_list, ICON_FA_LIST_CHECK " 插件列表", true)
{
    bool open = Begin (plugin_list_panel_name, nullptr, ImGuiWindowFlags_NoMove);
    if (open) {

        auto &plugins = PluginManager::instance()->get_plugins();
        PushStyleVar (ImGuiStyleVar_FrameRounding, GetFontSize()/2.f);
        PushStyleVar (ImGuiStyleVar_FramePadding, ImVec2(GetFontSize()/2.f, GetFontSize()/2.f));
        for (auto &p: plugins) {
            ImGuiID id = GetID(p.second.get());
            bool const loaded = p.second->is_loaded();
            bool const is_current_select = p.second->full_path.data() == selected_path;
            
            if (is_current_select) {
                PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.f);
                PushStyleColor(ImGuiCol_Border,  IM_COL32 (0xfd,0xb1,0x01,255));
                PushStyleColor(ImGuiCol_FrameBg, IM_COL32 (0x48,0x78,0x4a,0xff));
            }
            BeginChildFrame(id, ImVec2(0, GetTextLineHeightWithSpacing() * (loaded ? 6.f : 3.3f)));
            if (is_current_select) {
                PopStyleColor(2);
                PopStyleVar();
            }
            auto const name_color = ImColor(loaded ? IM_COL32(30,250,30,255) : IM_COL32(240,240,240,255));
            TextColored(name_color, "插件: %s", p.first.c_str());
            SameLine (0, GetFontSize());
            TextInformationSign ("路径: %s", p.second->full_path.c_str());
            if (loaded) {
                auto icon = p.second->plugin_inst->icon();
                if (icon) {
                    Texture *tex = (Texture*)icon->handle();
                    auto height = GetTextLineHeightWithSpacing();
                    SameLine (GetContentRegionMax().x - height - 8.f);
                    Image((ImTextureID)tex->Id(), ImVec2(height, height));
                }

            }
            Separator();
            Spacing();
            if (!loaded) {
                PushStyleColor (ImGuiCol_Text, IM_COL32 (240,180,10,255));
                CenterText("插件已禁用", GetContentRegionAvail().x);
                PopStyleColor ();
            } else {
                auto info = p.second->plugin_inst->get_plugin_info();
                if (info) {
                    Text("名称: %s", info->brief);
                    TextInformationSign("详细信息: %s", info->detail);
                    Spacing();
                    Text("作者: %s", info->author);
                    Spacing();
                    Text("版本: %d.%d.%d (%08x)", info->version_major, info->version_minor, info->version_patch, info->version_code);
                    TextInformationSign("开发者信息: %s", info->src_info);
                }
            }
            EndChildFrame();
            if (IsItemClicked()) {
                selected_plugin = p.second->plugin_inst;
                selected_path = p.second->full_path.data();
            } else if (is_current_select && IsItemClicked(ImGuiMouseButton_Right)) {
                selected_plugin = INVALID_PLUGIN;
                selected_path = nullptr;
            }
        }
        PopStyleVar (2);
    }
    End ();
}

PANEL_IMPL (plugin_content, ICON_FA_ROCKET " 插件内容", true)
{
    bool open = Begin (plugin_content_panel_name, nullptr, ImGuiWindowFlags_NoMove);
    if (open) {
        AlignTextToFramePadding ();
        if (!selected_plugin) {
            SetCursorPosY((GetContentRegionMax().y - GetTextLineHeightWithSpacing()) / 2.f);
            CenterText("插件尚未加载，当前无法查看！", GetContentRegionMax().x);
        } else if(selected_plugin == INVALID_PLUGIN) {
            ContentCenter ("尚未选中任何插件！");
        } else {
            auto ui = selected_plugin->content();
            if (!ui)
            {
                SetCursorPosY ((GetContentRegionMax ().y - GetTextLineHeightWithSpacing ()) / 2.f);
                CenterText (selected_plugin->name (), GetContentRegionMax ().x);
            }
            else
            {
                ui->draw();
            }
        }
    }
    End ();
}

PANEL_IMPL (ui_test, ICON_FA_FLASK_VIAL " UI测试", true)
{
    static ui_view       *layout = nullptr;
    static bindable_base *bind_data = nullptr;
    static std::string    ui_file;

    bool open = Begin(ui_test_panel_name);
    if (open) {
        if (Button("选择文件")) {
            FileDialog::Instance().Open ("ChooseUiFile", "选择界面布局文件", "UI文件 (*.pui) {.pui}");
        }
        ImGuiID view_id = GetID("数据查看器");
        SameLine(0, GetFontSize()*2.f);
        if (Button("查看数据")) {
            OpenPopup(view_id);
        }
        TextHelperSign("查看和编辑绑定数据");
        SameLine(0, GetFontSize()*2.f);
        if (Button("加载数据")) {
            load_ui_test_data(bind_data);
        }
        TextHelperSign("加载数据配置文件");
        SameLine(0, GetFontSize()*2.f);
        if (Button("保存数据")) {
            store_ui_test_data(bind_data);
        }
        TextHelperSign("保存数据到配置文件");
        SameLine(0, GetFontSize()*2.f);
        BeginDisabled(ui_file.empty());
        if (Button("重新加载UI文件")) {
            delete layout;
            layout = load_ui_file(ui_file);
            if (layout && bind_data)
                layout->bind(bind_data);
        }
        EndDisabled();
        SameLine(0, GetFontSize()*2.f);
        BeginDisabled(!layout || !bind_data);
        if (Button("重新绑定")) {
            layout->bind(bind_data);
        }
        EndDisabled();
        BulletText("当前选择文件：");
        SameLine();
        if (ui_file.empty())
            TextColored(ImVec4(1,1,0,1), "%s", "无");
        else
            TextColored(ImVec4(1,0,1,1), "%s", ui_file.c_str());
        SeparatorText ("\U0001F447 效果预览 \U0001F447");
        PushStyleColor (ImGuiCol_ChildBg, 0);
        bool preview_open = BeginChild("##UI_Preview", ImVec2(-1.f,-1.f));
        PopStyleColor ();
        if (preview_open)
        {
            if (!layout) {
                ContentCenter ("没有什么可以预览的 😊");
            } else
            {
                layout->draw();
            }
        }
        EndChild();
        CenterWindowPercent(.75f);
        if (FileDialog::Instance().IsDone("ChooseUiFile")) {
            if (FileDialog::Instance().HasResult()) {
                ui_file = FileDialog::Instance().GetResult().string();
                delete layout;
                layout = load_ui_file(ui_file);
                if (layout && bind_data)
                    layout->bind(bind_data);
            }
            FileDialog::Instance().Close();
        }
        show_ui_test_data(bind_data, "数据查看器");
    }
    End();
}

PANEL_IMPL (imgui_debug, ICON_FA_BUG " IMGUI TOOLS", false)
{
    ImGui::ShowDemoWindow(&imgui_debug_open);
    ImGui::ShowMetricsWindow(&imgui_debug_open);
}

#define PANEL_FULL(name, open) { name##_panel_name, open, name##_panel }
#define PANEL_ALWAYS_OPEN(name) PANEL_FULL (name, nullptr)
#define PANEL_CLOSABLE(name) PANEL_FULL (name, &name##_open)

const PanelInfo panels[] {
        PANEL_ALWAYS_OPEN (plugin_content),
        PANEL_ALWAYS_OPEN (plugin_list),
        PANEL_CLOSABLE (log),
        PANEL_CLOSABLE (ui_test),
        PANEL_CLOSABLE (imgui_debug),
};
const u32 panel_count = std::size(panels);
